#include "widget.h"
#include "ui_widget.h"

#include <QString>
#include <QTime>
#include <QDateTime>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 设置ai建议组件自动换行
    this->ui->label_ai_suggestion->setWordWrap(true);

    // 创建 自动模式定时器 和 定时模式定时器
    this->timer_auto_mode = new QTimer(this);
    this->timer_time_mode = new QTimer(this);

    // 绑定自动模式定时器， 定时结束通过socket向ai进程发送温湿度信息
    QObject::connect(this->timer_auto_mode, &QTimer::timeout, this, [=](){
        QString question = QString::number(this->temperature) + QString(",") + QString::number(this->humidity);
        this->socket_get_ai_answer->write(question.toUtf8());
        qDebug() << "已向ai_answer的socket发送：" + question << __LINE__ << __FILE__;
    });

    // 绑定定时模式定时器， 定时结束向mqtt服务器发送 关闭指令
    QObject::connect(this->timer_time_mode, &QTimer::timeout, this, [=](){
        // 重置日历编辑框， 更新为最新时间
        this->ui->dateTimeEdit->setDateTime(QDateTime::currentDateTime());
        // 重置定时模式选项， 恢复为打开
        this->ui->pushButton_timer_mode->setText("打开");

        QString command = QString("status+0");
        this->mqtt_client->publish(QMqttTopicName("stm32/command"), command.toUtf8(), 1, false);
        qDebug() << "已向mqtt主题 stm32/command 发送：" + command;
        this->timer_time_mode->stop();
    });

    // 初始化温度折线图
    this->chart_temperature_init();
    // 初始化湿度折线图
    this->chart_humidity_init();
    // 初始化mqtt服务器并连接
    this->mqtt_init();
    // 初始化日期编辑框
    this->DateTimeEdit_init();
}

/**
 * @brief Widget::mqtt_init
 * 初始化mqtt服务器， 连接服务器 并 订阅主题
 */
void Widget::mqtt_init()
{

    this->mqtt_client = new QMqttClient(this);

    this->mqtt_client->setHostname("192.168.247.205");
    this->mqtt_client->setPort(1883);
    this->mqtt_client->setUsername("sleep");
    this->mqtt_client->setPassword("520520");

    QObject::connect(this->mqtt_client, &QMqttClient::connected, this, []() {
        qDebug() << "已连接到MQTT服务器" << __LINE__ << __FILE__;
    });

    QObject::connect(this->mqtt_client, &QMqttClient::disconnected, []() {
        qDebug() << "已断开与MQTT服务器的连接" << __LINE__ << __FILE__;
    });

    QObject::connect(this->mqtt_client, &QMqttClient::errorChanged,[](QMqttClient::ClientError error) {
        qDebug() << "MQTT错误:" << error << __LINE__ << __FILE__;
    });


    connect(this->mqtt_client, &QMqttClient::connected, this, [=]() {

        auto subscription_status = this->mqtt_client->subscribe(QMqttTopicFilter("stm32/status"), 1);
        auto subscription_temperature = this->mqtt_client->subscribe(QMqttTopicFilter("stm32/data/temperature"), 1);
        auto subscription_humidity = this->mqtt_client->subscribe(QMqttTopicFilter("stm32/data/humidity"), 1);


        if (subscription_status && subscription_temperature && subscription_humidity)
        {
            connect(subscription_status, &QMqttSubscription::messageReceived, this, [=](const QMqttMessage &message) {
                // QString all_message = QString::fromStdString(message.payload().toStdString());
                // QStringList parts = all_message.split("+");

                if(message.payload().toInt() == 1)
                {
                    this->ui->label_source_status->setText("运行中");
                }
                else
                {
                    this->ui->label_source_status->setText("已关闭");
                }
            });

            connect(subscription_temperature, &QMqttSubscription::messageReceived, this, [=](const QMqttMessage &message) {

                this->temperature = message.payload().toDouble();
                this->series_temperature->append(QDateTime::currentMSecsSinceEpoch(), message.payload().toDouble());
                this->axisX_temperature->setRange(QDateTime::currentDateTime().addSecs(-50), QDateTime::currentDateTime());
            });

            connect(subscription_humidity, &QMqttSubscription::messageReceived, this, [=](const QMqttMessage &message) {
                this->humidity = message.payload().toDouble();
                this->series_humidity->append(QDateTime::currentMSecsSinceEpoch(), message.payload().toDouble());
                this->axisX_humidity->setRange(QDateTime::currentDateTime().addSecs(-50), QDateTime::currentDateTime());
            });
        }
        else
        {
            qDebug() << "主题订阅失败" << __LINE__ << __FILE__;
        }
    });


    this->mqtt_client->connectToHost();
}

/**
 * @brief Widget::chart_temperature_init
 * 初始化温度折线图
 */
void Widget::chart_temperature_init()
{
    // 布局初始化
    this->layout_temperature = new QVBoxLayout();
    this->ui->widget_temperature->setLayout(this->layout_temperature);
    this->ui->widget_temperature->setContentsMargins(0, 0, 0, 0);

    // 曲线系列设置
    this->series_temperature = new QLineSeries();
    this->series_temperature->setName("温度变化曲线");
    this->series_temperature->setPen(QPen(QColor(255, 99, 71), 2)); // 红色曲线，线宽2
    this->series_temperature->setPointsVisible(true); // 显示数据点
    this->series_temperature->setPointLabelsVisible(false); // 不显示数据标签

    // 添加曲线下方填充渐变
    QAreaSeries *areaSeries = new QAreaSeries(series_temperature);
    QLinearGradient gradient(QPointF(0, 0), QPointF(0, 1));
    gradient.setColorAt(0, QColor(255, 99, 71, 100)); // 半透明红色
    gradient.setColorAt(1, QColor(255, 99, 71, 10));  // 更透明的红色
    gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
    areaSeries->setBrush(gradient);
    areaSeries->setPen(QPen(Qt::NoPen)); // 区域边界不显示线条

    // 图表设置
    this->chart_temperature = new QChart();
    this->chart_temperature->addSeries(areaSeries); // 添加填充区域系列
    this->chart_temperature->addSeries(series_temperature); // 添加线系列（在区域上方）
    this->chart_temperature->setTitle("环境温度监测折线图");

    // 美化标题
    QFont titleFont = chart_temperature->titleFont();
    titleFont.setBold(true);
    titleFont.setPointSize(12);
    titleFont.setFamily("微软雅黑 UI");
    chart_temperature->setTitleFont(titleFont);
    chart_temperature->setTitleBrush(QBrush(QColor(60, 60, 60))); // 深灰色标题

    // 设置动画效果
    this->chart_temperature->setAnimationOptions(QChart::SeriesAnimations);
    this->chart_temperature->setAnimationDuration(1000); // 动画持续时间1秒

    // X轴（时间轴）设置
    this->axisX_temperature = new QDateTimeAxis();
    this->axisX_temperature->setTitleText("时间");
    this->axisX_temperature->setFormat("HH:mm:ss");
    this->axisX_temperature->setRange(QDateTime::currentDateTime().addSecs(-300),
                                      QDateTime::currentDateTime());
    this->axisX_temperature->setTickCount(6); // 6个刻度
    this->axisX_temperature->setGridLineVisible(true);
    this->axisX_temperature->setGridLinePen(QPen(QColor(220, 220, 220), 1, Qt::DotLine));
    this->axisX_temperature->setLabelsFont(QFont("微软雅黑 UI", 9)); // 设置字体，支持中文

    // Y轴（温度轴）设置
    QValueAxis *axisY = new QValueAxis();
    axisY->setTitleText("温度 (°C)");
    axisY->setRange(10, 40); // y轴范围
    axisY->setTickCount(7);  // 刻度数量
    axisY->setGridLineVisible(true);
    axisY->setGridLinePen(QPen(QColor(220, 220, 220), 1, Qt::DotLine));
    axisY->setLabelsFont(QFont("微软雅黑 UI", 9)); // 设置字体，支持中文
    axisY->setTitleBrush(QBrush(QColor(80, 80, 80))); // 轴标题颜色

    // 添加坐标轴
    this->chart_temperature->addAxis(this->axisX_temperature, Qt::AlignBottom);
    this->series_temperature->attachAxis(this->axisX_temperature);
    areaSeries->attachAxis(this->axisX_temperature);

    this->chart_temperature->addAxis(axisY, Qt::AlignLeft);
    this->series_temperature->attachAxis(axisY);
    areaSeries->attachAxis(axisY);

    // 图例设置
    chart_temperature->legend()->setVisible(true);
    chart_temperature->legend()->setAlignment(Qt::AlignTop);
    chart_temperature->legend()->setFont(QFont("微软雅黑 UI", 10));

    // 图表视图设置
    this->chartView_temperature = new QChartView(this->chart_temperature);
    this->chartView_temperature->setRenderHint(QPainter::Antialiasing);

    // 设置图表背景
    chartView_temperature->setBackgroundBrush(QBrush(QColor(255, 255, 255)));
    chart_temperature->setBackgroundBrush(QBrush(QColor(255, 255, 255)));

    // 添加边框
    chartView_temperature->setStyleSheet("border: 1px solid #e0e0e0; border-radius: 4px;");

    // 添加到布局
    this->layout_temperature->addWidget(this->chartView_temperature);

    // 添加数据提示（悬停时显示数值）
    QToolTip::setFont(QFont("微软雅黑 UI", 10));
    connect(series_temperature, &QLineSeries::hovered,
            this, [=](const QPointF &point, bool state) {
                if (state) {
                    QDateTime time = QDateTime::fromMSecsSinceEpoch(point.x());
                    QString tooltip = QString("%1\n温度: %2°C")
                                          .arg(time.toString("HH:mm:ss"))
                                          .arg(point.y(), 0, 'f', 1);
                    QToolTip::showText(QCursor::pos(), tooltip);
                }
            });
}

/**
 * @brief Widget::chart_humidity_init
 * 初始化湿度折线图
 */
void Widget::chart_humidity_init()
{
    // 布局初始化
    this->layout_humidity = new QVBoxLayout();
    this->ui->widget_humidity->setLayout(this->layout_humidity);
    this->ui->widget_humidity->setContentsMargins(0, 0, 0, 0);

    // 曲线系列设置
    this->series_humidity = new QLineSeries();
    this->series_humidity->setName("湿度变化曲线");
    this->series_humidity->setPen(QPen(QColor(60, 179, 113), 2)); // 绿色曲线，线宽2
    this->series_humidity->setPointsVisible(true); // 显示数据点
    this->series_humidity->setPointLabelsVisible(false); // 不显示数据标签

    // 添加曲线下方填充渐变
    QAreaSeries *areaSeries = new QAreaSeries(series_humidity);
    QLinearGradient gradient(QPointF(0, 0), QPointF(0, 1));
    gradient.setColorAt(0, QColor(60, 179, 113, 100)); // 半透明绿色
    gradient.setColorAt(1, QColor(60, 179, 113, 10));  // 更透明的绿色
    gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
    areaSeries->setBrush(gradient);
    areaSeries->setPen(QPen(Qt::NoPen)); // 区域边界不显示线条

    // 图表设置
    this->chart_humidity = new QChart();
    this->chart_humidity->addSeries(areaSeries); // 添加填充区域系列
    this->chart_humidity->addSeries(series_humidity); // 添加线系列（在区域上方）
    this->chart_humidity->setTitle("环境湿度监测折线图"); // 修正标题为湿度

    // 美化标题
    QFont titleFont = chart_humidity->titleFont();
    titleFont.setBold(true);
    titleFont.setPointSize(12);
    titleFont.setFamily("微软雅黑 UI");
    chart_humidity->setTitleFont(titleFont);
    chart_humidity->setTitleBrush(QBrush(QColor(60, 60, 60))); // 深灰色标题

    // 设置动画效果
    this->chart_humidity->setAnimationOptions(QChart::SeriesAnimations);
    this->chart_humidity->setAnimationDuration(1000); // 动画持续时间1秒

    // X轴（时间轴）设置
    this->axisX_humidity = new QDateTimeAxis();
    this->axisX_humidity->setTitleText("时间");
    this->axisX_humidity->setFormat("HH:mm:ss");
    this->axisX_humidity->setRange(QDateTime::currentDateTime().addSecs(-300),
                                   QDateTime::currentDateTime());
    this->axisX_humidity->setTickCount(6); // 6个刻度
    this->axisX_humidity->setGridLineVisible(true);
    this->axisX_humidity->setGridLinePen(QPen(QColor(220, 220, 220), 1, Qt::DotLine));
    this->axisX_humidity->setLabelsFont(QFont("微软雅黑 UI", 9)); // 设置字体，支持中文
    this->axisX_humidity->setTitleBrush(QBrush(QColor(80, 80, 80)));

    // Y轴（湿度轴）设置
    QValueAxis *axisY = new QValueAxis();
    axisY->setTitleText("湿度 (%)");
    axisY->setRange(0, 100); // y轴范围
    axisY->setTickCount(11);  // 刻度数量
    axisY->setGridLineVisible(true);
    axisY->setGridLinePen(QPen(QColor(220, 220, 220), 1, Qt::DotLine));
    axisY->setLabelsFont(QFont("微软雅黑 UI", 9)); // 设置字体，支持中文
    axisY->setTitleBrush(QBrush(QColor(80, 80, 80))); // 轴标题颜色

    // 添加坐标轴
    this->chart_humidity->addAxis(this->axisX_humidity, Qt::AlignBottom);
    this->series_humidity->attachAxis(this->axisX_humidity);
    areaSeries->attachAxis(this->axisX_humidity);

    this->chart_humidity->addAxis(axisY, Qt::AlignLeft);
    this->series_humidity->attachAxis(axisY);
    areaSeries->attachAxis(axisY);

    // 图例设置
    chart_humidity->legend()->setVisible(true);
    chart_humidity->legend()->setAlignment(Qt::AlignTop);
    chart_humidity->legend()->setFont(QFont("SimHei", 10));
    chart_humidity->legend()->setLabelColor(QColor(60, 60, 60));

    // 图表视图设置
    this->chartView_humidity = new QChartView(this->chart_humidity);
    this->chartView_humidity->setRenderHint(QPainter::Antialiasing);

    // 设置图表背景
    chartView_humidity->setBackgroundBrush(QBrush(QColor(255, 255, 255)));
    chart_humidity->setBackgroundBrush(QBrush(QColor(255, 255, 255)));

    // 添加边框和阴影效果
    chartView_humidity->setStyleSheet("border: 1px solid #e0e0e0; border-radius: 4px;");

    // 添加到布局
    this->layout_humidity->addWidget(this->chartView_humidity);

    // 添加数据提示（悬停时显示数值）
    QToolTip::setFont(QFont("微软雅黑 UI", 10));
    connect(series_humidity, &QLineSeries::hovered,
            this, [=](const QPointF &point, bool state) {
                if (state) {
                    QDateTime time = QDateTime::fromMSecsSinceEpoch(point.x());
                    QString tooltip = QString("%1\n湿度: %2%")
                                          .arg(time.toString("HH:mm:ss"))
                                          .arg(point.y(), 0, 'f', 1);
                    QToolTip::showText(QCursor::pos(), tooltip);
                }
            });
}

/**
 * @brief Widget::DateTimeEdit_init
 * 初始化日历编辑框
 */
void Widget::DateTimeEdit_init()
{
    this->ui->checkBox_customize_endTime->setCheckState(Qt::Unchecked);
    this->ui->dateTimeEdit->setEnabled(false);
    this->ui->dateTimeEdit->setDateTime(QDateTime::currentDateTime());
    this->ui->dateTimeEdit->setDisplayFormat("yyyy/MM/dd HH:mm:ss");
}

Widget::~Widget()
{
    delete ui;
}

/**
 * @brief Widget::socket_init
 * 初始化与 ai进程通信的套接字 并连接
 */
void Widget::socket_init()
{
    this->socket_get_ai_answer = new QTcpSocket(this);
    this->socket_get_ai_answer->connectToHost(QHostAddress("127.0.0.1"), 55555);

    QObject::connect(this->socket_get_ai_answer, &QTcpSocket::connected, this, [=](){
        qDebug() << "ai_answer的socket已连接到IP：127.0.0.1 端口：55555" << __LINE__ << __FILE__;
        QString question = QString::number(this->temperature) + QString(",") + QString::number(this->humidity);
        this->socket_get_ai_answer->write(question.toUtf8());
        qDebug() << "已向ai_answer的socket发送：" + question << __LINE__ << __FILE__;
    });

    QObject::connect(this->socket_get_ai_answer, &QTcpSocket::readyRead, this, [=](){
        QString data = this->socket_get_ai_answer->readAll();
        qDebug() << "ai_answer的socket收到来自ai的回答：" << data << __LINE__ << __FILE__;

        QStringList part_data = data.split("+");
        QString command = QString("speed+") + part_data[0];
        this->mqtt_client->publish(QMqttTopicName("stm32/command"), command.toUtf8(), 1, false);
        qDebug() << "已向mqtt主题 stm32/command 发送：" + command;

        this->ui->label_ai_suggestion->setText(part_data[1]);

    });

}

/**
 * @brief Widget::socket_delete
 * 关闭并删除与ai进程通信的套接字
 */
void Widget::socket_delete()
{
    if (socket_get_ai_answer)
    {
        socket_get_ai_answer->disconnectFromHost();
        socket_get_ai_answer->waitForDisconnected(1000);
        delete socket_get_ai_answer;
        socket_get_ai_answer = nullptr;
    }
}

/**
 * @brief Widget::on_horizontalSlider_speed_valueChanged
 * 滑块数值发送改变后更新用于显示其值的QLabel
 * @param value
 * 改变后的值
 */
void Widget::on_horizontalSlider_speed_valueChanged(int value)
{
    this->ui->label_speed->setText(QString::number(value) + "%");
}

/**
 * @brief Widget::on_horizontalSlider_speed_sliderReleased
 * 滑块释放后向mqtt发送 转速更新指令
 */
void Widget::on_horizontalSlider_speed_sliderReleased()
{
    int value = this->ui->horizontalSlider_speed->value();
    QString command = QString("speed+") + QString::number(value);
    this->mqtt_client->publish(QMqttTopicName("stm32/command"), command.toUtf8(), 1, false);
    qDebug() << "已向mqtt主题 stm32/command 发送：" + command;
}

/**
 * @brief Widget::on_pushButton_auto_mode_clicked
 * 自动模式打开后，1.启动ai进程 2.通过socket连接并通信 3.自动模式定时器开启
 * 自动模式关闭后，1.自动模式定时器关闭 2.关闭socket连接 3.关闭ai进程
 */
void Widget::on_pushButton_auto_mode_clicked()
{
    if(this->ui->pushButton_auto_mode->text() == "打开")
    {
        this->ui->pushButton_energy_saving_mode->setEnabled(false);
        this->ui->horizontalSlider_speed->setEnabled(false);

        // 启动ai进程
        this->process_hunyuan = new QProcess(this);
        QString exePath = QCoreApplication::applicationFilePath();
        QString dirPath = QFileInfo(exePath).absolutePath();
        this->process_hunyuan->start(dirPath+ "/Tools/hunyuan.exe");
        if (this->process_hunyuan->waitForStarted(3000))
        {
            qDebug() << "进程启动成功";
            // 通过socket连接并通信
            this->socket_init();
        }
        else
        {
            qDebug() << "进程启动失败:" << this->process_hunyuan->errorString();
        }

        // 自动模式定时器开启
        this->timer_auto_mode->start(5000);
        this->ui->pushButton_auto_mode->setText("关闭");
    }
    else
    {
        // 自动模式定时器关闭
        this->timer_auto_mode->stop();
        // 关闭socket连接
        this->socket_delete();
        // 关闭ai进程
        if (this->process_hunyuan->state() == QProcess::Running)
        {
            this->process_hunyuan->terminate();
            qDebug() << "已向进程发送终止信号";
        }

        this->ui->pushButton_energy_saving_mode->setEnabled(true);
        this->ui->horizontalSlider_speed->setEnabled(true);

        this->ui->pushButton_auto_mode->setText("打开");
    }
}

/**
 * @brief Widget::on_checkBox_customize_endTime_clicked
 * 切换定时时间设置方式
 */
void Widget::on_checkBox_customize_endTime_clicked()
{
    if(this->ui->checkBox_customize_endTime->checkState() == Qt::CheckState::Checked)
    {
        this->ui->comboBox->setEnabled(false);
        this->ui->dateTimeEdit->setEnabled(true);
    }
    else
    {
        this->ui->comboBox->setEnabled(true);
        this->ui->dateTimeEdit->setEnabled(false);
    }
}

/**
 * @brief Widget::on_pushButton_timer_mode_clicked
 * 通过用户选择的时间启动定时模式定时器
 */
void Widget::on_pushButton_timer_mode_clicked()
{
    if(this->ui->pushButton_timer_mode->text() == "启动")
    {
        if(this->ui->checkBox_customize_endTime->isChecked())
        {
            qint64 time_seconds = QDateTime::currentDateTime().secsTo(this->ui->dateTimeEdit->dateTime());
            this->timer_time_mode->start(time_seconds);
        }
        else
        {
            if(this->ui->comboBox->currentText() == "15分钟")
            {
                this->timer_time_mode->start(15 * 60);
            }
            else if(this->ui->comboBox->currentText() == "30分钟")
            {
                this->timer_time_mode->start(30 * 60);
            }
            else if(this->ui->comboBox->currentText() == "1小时")
            {
                this->timer_time_mode->start(60 * 60);
            }
            else if(this->ui->comboBox->currentText() == "2小时")
            {
                this->timer_time_mode->start(120 * 60);
            }
            else if(this->ui->comboBox->currentText() == "4小时")
            {
                this->timer_time_mode->start(240 * 60);
            }
            else if(this->ui->comboBox->currentText() == "8小时")
            {
                this->timer_time_mode->start(480 * 60);
            }
        }
        this->ui->pushButton_timer_mode->setText("关闭");
    }
    else
    {
        this->timer_time_mode->stop();
        this->ui->pushButton_timer_mode->setText("启动");
    }
}

